﻿using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Centido.Core.Test
{
    /// <summary>
    ///   Testing when the recycle bin is off.
    /// </summary>
    [TestClass]
    public class TurningRecycleBinOff
    {
        /// <summary>
        /// Domain name
        /// </summary>
        public const string DomainName = "FullAdminRights";

        /// <summary>
        /// Domain
        /// </summary>
        private Domain _domain;

        /// <summary>
        /// A table in the domain
        /// </summary>
        private Table _table;

        /// <summary>
        /// Name of that table
        /// </summary>
        private string _tableName;


        /// <summary>
        /// Initializing the test
        /// </summary>
        [TestInitialize]
        public void Initialize()
        {
            _domain = Domain.Build(DomainConfiguration.Load(DomainName));

            _domain.DeleteAllTables();

            _tableName = StringProperty.RandomIdentifier();

            _table = _domain.AddTable(_tableName);

            _table.GrantAll();
        }

        /// <summary>
        /// Cleaning up after the test
        /// </summary>
        [TestCleanup]
        public void CleanUp()
        {
            _domain.DeleteAllTables();
        }


        /// <summary>
        ///   Reading and writing the recycle bin option
        /// </summary>
        [TestMethod]
        public void ReadingAndWritingRecycleBin()
        {
            _domain.HasRecycleBin = false;
            _domain.HasRecycleBin = false;

            Assert.IsFalse(_domain.HasRecycleBin);

            _domain.HasRecycleBin = true;
            _domain.HasRecycleBin = true;

            Assert.IsTrue(_domain.HasRecycleBin);
        }


        /// <summary>
        ///   Checking that deleted rows reappear when the recycle bin is turned off.
        /// </summary>
        [TestMethod]
        public void CheckingThatDeletedRowsReappear()
        {
            //Turning the recycle bin on
            _domain.HasRecycleBin = true;

            //Creating another table
            var anotherTable = _domain.AddTable(StringProperty.RandomIdentifier());
            anotherTable.GrantAll();

            //Creating the ref
            var refColumn = RefColumn.Add(_table, StringProperty.RandomIdentifier());
            refColumn.AddTarget(anotherTable).HasCascadeDelete = true;

            //Inserting a chain of rows
            var rowId = anotherTable.InsertRow();
            _table.InsertRow(refColumn.Value(rowId));

            //Deleting the chain of rows
            anotherTable.DeleteRow(rowId);

            Assert.AreEqual(anotherTable.RowCount, 0);
            Assert.AreEqual(_table.RowCount, 0);

            //Turning the recycle bin off
            _domain.HasRecycleBin = false;

            Assert.AreEqual(anotherTable.RowCount, 1);
            Assert.AreEqual(_table.RowCount, 1);

            //Turning the recycle bin on
            _domain.HasRecycleBin = true;

            Assert.AreEqual(anotherTable.RowCount, 0);
            Assert.AreEqual(_table.RowCount, 0);
        }


        /// <summary>
        ///   Checking that rows are deleted permanently.
        /// </summary>
        [TestMethod]
        public void CheckingThatRowsAreDeletedPermanently()
        {
            var id = _table.InsertRow();

            _domain.HasRecycleBin = false;

            Assert.AreEqual(_table.RowCount, 1);
            Assert.AreEqual(_table.InternalRowCount, 1);

            _table.DeleteRow(id);

            Assert.AreEqual(_table.RowCount, 0);
            Assert.AreEqual(_table.InternalRowCount, 0);
        }


        /// <summary>
        ///   Checking that an ordinary user can delete rows permanently.
        /// </summary>
        [TestMethod]
        public void CheckingThatOrdinaryUserCanDeleteRowsPermanently()
        {
            //  Creating an ordinary user
            var userName = StringProperty.RandomIdentifier();
            var userPassword = StringProperty.RandomPassword();
            _domain.AddUser(userName, userPassword);

            _table.GrantAll(userName);

            _domain.HasRecycleBin = false;

            var userDomain = _domain.Logon(userName, userPassword);

            var userTable = userDomain.GetTable(_tableName);

            var id = userTable.InsertRow();

            Assert.AreEqual(_table.RowCount, 1);
            Assert.AreEqual(_table.InternalRowCount, 1);

            userTable.DeleteRow(id);

            Assert.AreEqual(_table.RowCount, 0);
            Assert.AreEqual(_table.InternalRowCount, 0);
        }


        /// <summary>
        ///   Checking that unit level security can be turned off at the same time.
        /// </summary>
        [TestMethod]
        public void CheckingThatUnitLevelSecurityCanBeTurnedOffAtTheSameTime()
        {
            _domain.HasRecycleBin = false;
            _table.HasUnitLevelSecurity = false;

            var id = _table.InsertRow();

            Assert.AreEqual(_table.RowCount, 1);
            Assert.AreEqual(_table.InternalRowCount, 1);

            _table.DeleteRow(id);

            Assert.AreEqual(_table.RowCount, 0);
            Assert.AreEqual(_table.InternalRowCount, 0);
        }
    }
}
